﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using WowParserLib.Events;

namespace WowParserLib
{
    public delegate void LineReadDelegate(string line);
 
    public delegate void LogParsedDelegate(IList<Actor> actors);

    public class WowLogParser
    {
        private string _logFilePath;
        private EventsFactory _eventFactory;
        private IEventIdProvider _eventIdProvider;

        public event LogParsedDelegate LogParsed;

        private IDictionary<ulong, Actor> _actors;

        public WowLogParser(string logFilePath)
        {
            _logFilePath = logFilePath;
            _actors = new Dictionary<ulong, Actor>();
            _eventIdProvider = new EventIdProvider();
            _eventFactory = new EventsFactory(_eventIdProvider); // Coupling...
            
        }

        public void Parse()
        {
            using (StreamReader fs = new StreamReader(_logFilePath, true))
            {
                while (fs.Peek() > -1)
                {
                    string line = fs.ReadLine();
                    Actor source = GetSourceActor(line);
                    if (_actors.ContainsKey(source.Id))
                    {
                        source = _actors[source.Id];
                    }
                    else
                    {
                        _actors.Add(source.Id, source);
                    }
                    Actor target = GetDestinationActor(line);
                    if (target != null)
                    {
                        if (_actors.ContainsKey(target.Id))
                        {
                            target = _actors[target.Id];
                        }
                        else
                        {
                            _actors.Add(target.Id, target);
                        }
                    }
                    Event e = _eventFactory.Create(line, source, target);
                    e.Source.AddSourceEvent(e);
                    e.Target.AddTargetEvent(e);
                }
            }
            OnLogParsed(_actors.Values.ToList<Actor>());
        }

        //timestamp	event	sourceGUID	sourceName	sourceFlags	destGUID	destName	destFlags
        private Actor GetSourceActor(string line)
        {
            string[] split = line.Split(',');
            ulong id = Convert.ToUInt64(split[1], 16);
            if (id == 0)
            {
                return new NullActor();
            }
            else
            {
                return new Actor(id, split[2].Replace("\"", ""));
            }
        }

        private Actor GetDestinationActor(string line)
        {
            string[] split = line.Split(',');
            if (split.Length > 6)
            {
                ulong id = Convert.ToUInt64(split[4], 16);
                return new Actor(id, split[5].Replace("\"", ""));
            }
            else
                return new NullActor(); ;
        }

        private void OnLogParsed(IList<Actor> actors)
        {
            if (LogParsed != null)
            {
                LogParsed(actors);
            }
        }
    }
}
